# -*- coding=utf-8 -*-
import time
from shutil import copy
from ctypes import *

class sDepMarketData(Structure):
    _fields_ = [('TradingDay', 			c_char * 9),
                ('InstrumentID',		c_char * 31),
                ('ExchangeID',			c_char * 9),
                ('ExchangeInstID',		c_char * 31),
                ('LastPrice',			c_double),
                ('PreSettlementPrice', 	c_double),
                ('PreClosePrice',		c_double),
                ('PreOpenInterest',		c_double),
                ('OpenPrice',			c_double),
                ('HighestPrice',		c_double),
                ('LowestPrice',			c_double),
                ('Volume',				c_int),
                ('Turnover',			c_double),
                ('OpenInterest',		c_double),
                ('ClosePrice',			c_double),
                ('SettlementPrice',		c_double),
                ('UpperLimitPrice',		c_double),
                ('LowerLimitPrice',		c_double),
                ('PreDelta',			c_double),
                ('CurrDelta',			c_double),
                ('UpdateTime',			c_char * 9),
                ('UpdateMillisec',		c_int32),
                ('BidPrice1', 			c_double),
                ('BidVolume1',			c_int32),
                ('AskPrice1',			c_double),
                ('AskVolume1',			c_int32),
                ('BidPrice2',			c_double),
                ('BidVolume2',			c_int32),
                ('AskPrice2',			c_double),
                ('AskVolume2',			c_int32),
                ('BidPrice3',			c_double),
                ('BidVolume3',			c_int32),
                ('AskPrice3',			c_double),
                ('AskVolume3',			c_int32),
                ('BidPrice4',			c_double),
                ('BidVolume4',			c_int32),
                ('AskPrice4',			c_double),
                ('AskVolume4',			c_int32),
                ('BidPrice5',			c_double),
                ('BidVolume5',			c_int32),
                ('AskPrice5',			c_double),
                ('AskVolume5',			c_int32),
                ('AveragePrice',		c_double)
    ]
    pass


class QL_CThostFtdcRspUserLoginField(Structure):
    _fields_ = [('TradingDay', 			     c_char * 9),       #交易日
                ('LoginTime',		             c_char * 9),       #登录成功时间
                ('BrokerID',		             c_char * 11),      #经纪公司代码
                ('UserID',		             c_char * 16),      #用户代码
                ('SystemName',		             c_char * 41),      #交易系统名称
                ('FrontID',		             c_int32),          #前置编号
                ('SessionID',		             c_int32),          #会话编号
                ('MaxOrderRef',		             c_char * 13),      #最大报单引用
                ('SHFETime',		             c_char * 9),       #上期所时间
                ('DCETime',		             c_char * 9),       #大商所时间
                ('CZCETime',		             c_char * 9),       #郑商所时间
                ('FFEXTime',		             c_char * 9),       #中金所时间
                ('INETime',		             c_char * 9)        #能源中心时间
                ]
    pass


class QL_Instrument(Structure):
    _fields_ = [('InstrumentID',c_char * 31)]
    pass


class QL_CThostFtdcRspInfoField(Structure):
    _fields_ = [('ErrorID', 			     c_int32),       #错误代码
                ('ErrorMsg',		             c_char * 81)    #错误信息
                ]
    pass

class QL_CThostFtdcForQuoteRspField(Structure):
    _fields_ = [('TradingDay', 			     c_char * 9),    #交易日
                ('InstrumentID',		             c_char * 31),   #合约代码
                ('ForQuoteSysID',		             c_char * 21),   #询价编号
                ('ForQuoteTime',		             c_char * 9),    #询价时间
                ('ActionDay',		             c_char * 9),    #业务日期
                ('ExchangeID',		             c_char * 9)     #交易所代码
                ]
    pass

NULL    =100





# PRICE TYPE
QL_CLOSE 					= 10010 #c_char('0')	# 收盘价
QL_OPEN 					= 10011 #c_char('1')	# 开盘价
QL_HIGH 					= 10012 #c_char('2')	# 最高价
QL_LOW 					        = 10013 #c_char('3')	# 最低价

##################################################################################################################################
##################################################################################################################################
##################################################################################################################################
##################################################################################################################################
##################################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################
##############################################################################################################################

MD_EMPTY                    = 8000 #无消息
MD_LOGIN_SCUESS             = 8001 #登录成功
MD_LOGIN_DENIED             = 8002 #登录被拒绝
#MD_LOGIN_ERRORPASSWORD     = 8003 #密码错误(行情没有密码错误)
MD_LOGINOUT_SCUESS          = 8004 #登出成功
MD_NETCONNECT_SCUESS        = 8005 #连接成功
MD_NETCONNECT_BREAK         = 8006 #断开连接
MD_NETCONNECT_FAILER        = 8007 #连接失败
MD_SUBCRIBE_SCUESS          = 8008 #订阅成功
MD_UNSUBCRIBE_SCUESS        = 8009 #取消订阅成功
MD_NEWTICK                  = 8010 #新Tick到来
MD_SYSTEM_ERROR             = 8011 #错误应答
MD_QRY_FORQUOTE             = 8012 #询价通知


mddict={
          MD_EMPTY:'MD_EMPTY',
          MD_LOGIN_SCUESS:'MD_LOGIN_SCUESS',
          MD_LOGIN_DENIED:'MD_LOGIN_DENIED',
          MD_LOGINOUT_SCUESS:'MD_LOGINOUT_SCUESS',
          MD_NETCONNECT_SCUESS:'MD_NETCONNECT_SCUESS',
          MD_NETCONNECT_BREAK:'MD_NETCONNECT_BREAK',
          MD_NETCONNECT_FAILER:'MD_NETCONNECT_FAILER',
          MD_SUBCRIBE_SCUESS:'MD_SUBCRIBE_SCUESS',
          MD_UNSUBCRIBE_SCUESS:'MD_UNSUBCRIBE_SCUESS',
          MD_NEWTICK:'MD_NEWTICK',
          MD_SYSTEM_ERROR:'MD_SYSTEM_ERROR',
          MD_QRY_FORQUOTE:'MD_QRY_FORQUOTE'
        }



import os
import sys
import datetime
import struct
GPATH= os.path.split(os.path.realpath(__file__))[0]
PATH_LOG_FILE = GPATH + os.sep + 'hqsenderlog.txt'





def WrieTxtLogFile(log_content):
    try:
        output = open(PATH_LOG_FILE, 'a')
        output.write(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+"-->"+log_content + '\n')
        output.close()
    except Exception as e:
        logerro(e)

def logerro(e):
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
    return "exc_type"+ str(exc_type) + "fname"+ str(fname) + "line:"+ str(exc_tb.tb_lineno) + ":"+str(e)

def SetStdCtpDll(is32bit):
    try:
        gpath = os.path.split(os.path.realpath(__file__))[0]
        file1 = 'thostmduserapi.dll'
        file2 = 'thosttraderapi.dll'
        path1 = gpath+os.sep+file1
        path2 = gpath+os.sep+file2
        os.remove(path1)
        os.remove(path2)
        if is32bit:
            copy(gpath+os.sep +'ctpdll32' + os.sep + file1 ,gpath+os.sep+file1)
            copy(gpath+os.sep +'ctpdll32' + os.sep + file2 ,gpath+os.sep+file2)
        else:
            copy(gpath + os.sep + 'ctpdll64' + os.sep + file1, gpath + os.sep + file1)
            copy(gpath + os.sep + 'ctpdll64' + os.sep + file2, gpath + os.sep + file2)
    except Exception as e:
        logerro(e)






class CTPMarket(object):
    def __init__(self):
        gpath = os.path.split(os.path.realpath(__file__))[0]
        dllfile = 'FBYXHQAPI_32bit.dll' # default is 32bit
        #if not struct.calcsize("P") == 4: #64bit
        #    dllfile = 'FBYXHQAPI_64bit.dll'
        #    SetStdCtpDll(False)
        #else:
        #    SetStdCtpDll(True)
        self.d2 = CDLL(gpath + os.sep +dllfile)
        i = 0
        while (i < 10):
            time.sleep(1)
            if (self.d2.IsInitOK() == 0):
                i += 1
            else:
                break
        else:
            print('------->>>>>>>>>>>market init error!!!!!!!<<<<<<<<<<<<<<<<<<<<<-------------------')
            return

        self.fReqUserLogin = self.d2.ReqUserLogin #
        self.fReqUserLogin.argtypes = []
        self.fReqUserLogin.restype = c_int32

        self.fReqUserLogout = self.d2.ReqUserLogout
        self.fReqUserLogout.argtypes = []
        self.fReqUserLogout.restype = c_int32

        self.fUnSubscribeMarketData = self.d2.UnSubscribeMarketData
        self.fUnSubscribeMarketData.argtypes = [c_char_p]

        self.fOnEvent = self.d2.OnEvent
        self.fOnEvent.argtypes = []
        self.fOnEvent.restype = c_int32

        self.fGet_Tick_Name = self.d2.Get_Tick_Name
        self.fGet_Tick_Name.argtypes = []
        self.fGet_Tick_Name.restype = c_char_p

        self.fGetApiVersion = self.d2.GetApiVersion
        self.fGetApiVersion.argtypes = []
        self.fGetApiVersion.restype = c_char_p

        self.fGetTickData = self.d2.GetTickData
        self.fGetTickData.argtypes = [c_int32]
        self.fGetTickData.restype = c_void_p

        self.fSubscribe = self.d2.Subscribe
        self.fSubscribe.argtypes = [c_char_p]

        #self.fSubscribeForQuoteRsp = self.d2.SubscribeForQuoteRsp
        #self.fSubscribeForQuoteRsp.argtypes = [c_char_p]

        self.fResetIndex = self.d2.ResetIndex

        self.InstrumentNum = self.d2.GetInstrumentNum()
        self.Index = dict()
        print('CTP Api Version:')
        print(str(self.GetApiVersion()))
        # 订阅合约时，请注意合约的大小写，中金所和郑州交易所是大写，上海和大连期货交易所是小写的


    # 订阅询价
    def SubscribeForQuoteRsp(self, contract):
        # 订阅合约时，请注意合约的大小写，中金所和郑州交易所是大写，上海和大连期货交易所是小写的
        #self.fSubscribeForQuoteRsp(c_char_p(contract))
        pass

    def Subcribe(self, contract):
        # 订阅合约时，请注意合约的大小写，中金所和郑州交易所是大写，上海和大连期货交易所是小写的
        if type(contract)==str:
            contract = contract.encode('utf8') # change to byte
        self.fSubscribe(c_char_p(contract))
        if type(contract) == bytes:
            contract = contract.decode('utf8')
        data = self.fGetTickData(len(self.Index))
        data = cast(data, POINTER(sDepMarketData))
        self.Index[contract] = data
        return self.Index[contract][0]


    def Login(self):
        return self.fReqUserLogin()

    def Logout(self):
        return self.fReqUserLogout()

    def UnSubscribeMarketData(self, contract):
        if type(contract)==str:
            contract = contract.encode('utf8') # change to byte
        return self.fUnSubscribeMarketData(contract)

    def Get_Tick_Name(self):
        Instrument = self.fGet_Tick_Name()  # 获取是哪个合约发来的新的tick
        if type(Instrument) == bytes:
            Instrument = Instrument.decode('utf8')  #
        return Instrument

    def GetApiVersion(self):
        return self.fGetApiVersion()

    def ResetIndex(self):
        return self.fResetIndex()
    
    def OnEvent(self):
        mEvent = self.fOnEvent()
        if mEvent in mddict:
            if mEvent!=MD_NEWTICK:
                print(mddict[mEvent]) 
                if mEvent==MD_NETCONNECT_BREAK: # 网络断开后清空索引
                    self.Index = dict()
                    self.ResetIndex()
        return mEvent   
####################################################################################################################################################
####################################################################################################################################################
####################################################################################################################################################
####################################################################################################################################################

    





